import { Http } from '@/service/Http/index.js'
import Utils from '@/utils/Utils.js'
import _ from '@/libs/lodash.min.js'
import $ from 'jquery'
import config from '@/global/config.js'

let datafeed = {}
let tradingView = {}
let tradingViewHandle = {}

datafeed = {
  onReady: (configurationData) => {
    // console.info('onReady')
    setTimeout(() => {
      configurationData({
        'supports_search': true,
        'supports_group_request': false,
        'supports_marks': true,
        'exchanges': [{
          'value': '',
          'name': '所有交易所',
          'desc': '所有交易所'
        }],
        'symbolsTypes': [{
          'value': '',
          'name': '所有'
        }],
        'supported_resolutions': ['1', '5', '15', '30', '60', 'D', 'W', 'M']
      })
    }, 0)
  },
  searchSymbolsByName: (userInput, exchange, symbolType, onResultReadyCallback) => {
    // console.info('searchSymbolsByName', userInput, exchange, symbolType, onResultReadyCallback)
    onResultReadyCallback([{
      'symbol': 'BTC/USD', // 商品缩写名
      'full_name': 'BTC/USD', // 商品全称
      'description': 'BTC/USD',
      'exchange': config.siteName, //
      'ticker': '', // <商品代号, 可选>
      'type': 'bitcoin' // 'stock' | 'futures' | 'bitcoin' | 'forex' | 'index'
    }])
  },
  resolveSymbol: (symbolName, onSymbolResolvedCallback, onResolveErrorCallback) => {
    // 通过商品名称解析商品信息(SymbolInfo)。
    // console.info('resolveSymbol', symbolName) // 商品名称 或ticker if provided.
    setTimeout(() => { // settimeout必须
      onSymbolResolvedCallback({
        'name': tradingView.options.pair.Symbol,
        'exchange-traded': config.siteName,
        'exchange-listed': config.siteName,
        'timezone': 'Asia/Hong_Kong',
        'minmov': 1,
        'minmov2': 0,
        'pricescale': Math.pow(10, tradingView.options.pair.buyerPrecision || 1), // 小数位精度=minmov / pricescale
        'pointvalue': 1,
        'has_intraday': true,
        'has_no_volume': false,
        'volume_precision': 0,
        'ticker': tradingView.options.pair.Symbol, // 商品唯一标识，不设则切换为平均K线图就会报错
        'description': tradingView.options.pair.Symbol,
        'type': 'bitcoin',
        'has_daily': true,
        'has_weekly_and_monthly': true,
        'supported_resolutions': ['1', '5', '15', '30', '60', 'D', 'W', 'M'],
        'intraday_multipliers': ['1', '5', '15', '30', '60'],
        'session': '24x7',
        'data_status': 'streaming'
      })
    }, 0)
  },
  getBars: (symbolInfo, resolution, from, to, onHistoryCallback, onErrorCallback, firstDataRequest) => {
    // console.log('getBars', symbolInfo)
    // 点击左下角的时间范围内
    // 这里在EDGE会报错导致不运行，所以加上try
    try {
      tradingView.resolutionBtnNodes && tradingView.resolutionBtnNodes.forEach((node) => {
        if (node.attr('data-resolution') === resolution) {
          node.addClass('active').closest('.space-single').siblings().find('.active').removeClass('active')
        }
      })
      let lineTypes = {
        '1': 101,
        '5': 102,
        '15': 103,
        '30': 104,
        '60': 201,
        'D': 301,
        'W': 310,
        'M': 401
      }
      let lineType = lineTypes[resolution.toString()]
      tradingViewHandle.lineType = lineType
      tradingView.pageIndex++
      // 切换k线周期要重置0，不然若用户拖到后面，而后台却没有这后面的数据，会显示空白
      if (tradingView.lineType !== lineType) {
        tradingView.pageIndex = 1
      }
      tradingView.lineType = lineType
      Http.get('LineData/GetLineData/', {
          TradingConfigId: tradingView.options.pair.TradingConfigID,
          PageIndex: tradingView.pageIndex,
          PageSize: 200,
          LineType: lineType,
          ClientType: 0, // Web = 0 Android = 1 iOS = 2 H5 = 4
          LanguageCode: tradingView.options.language
        }, {
          // mock: 'kline',
          isQueryString: true
        })
        .then((res) => {
          let data = res.Data || []
          let _data = []
          let currentTime
          let nextTime

          // Utils.setUTCWithArray(data, 'DealDate')
          /*for (let i = 0; i < data.length; i++) {
            // 时间重复会导致K线显示，提示Incremental update failed
            currentTime = Utils.fixNewDateForIE(data[i].DealDate).getTime()

            if (data[i + 1]) {
              nextTime = Utils.fixNewDateForIE(data[i + 1].DealDate).getTime()
              if (currentTime < nextTime || currentTime === nextTime) {
                // console.log('判断', data[i].DealDate)
                // console.log('判断', data[i + 1].DealDate)
                // console.log('判断', data[i].Closed, data[i].Opened, data[i].Highest, data[i].Lowest, data[i].DNum)
                // console.log('判断', data[i + 1].Closed, data[i + 1].Opened, data[i + 1].Highest, data[i + 1].Lowest, data[i + 1].DNum)
                continue
              }
            }

            _data.push({
              time: currentTime,
              close: data[i].Closed,
              open: data[i].Opened,
              high: data[i].Highest,
              low: data[i].Lowest,
              volume: data[i].DNum
            })
          }*/

          data.every((x) => {
            _data.push({
              time: Utils.fixNewDateForIE(x.DealDate).getTime(),
              close: x.Closed,
              open: x.Opened,
              high: x.Highest,
              low: x.Lowest,
              volume: x.DNum
            })
            return true
          })

          if (!firstDataRequest) {
            _data.reverse()
            datafeed.fillData(_data, resolution, onHistoryCallback)
            return
          }

          // 没有处理过当前最新的有效数据时间
          if (firstDataRequest && resolution !== 'W' && resolution !== 'M') {
            datafeed.fillCurrentLastDate(_data, to, resolution, function(data) {
              datafeed.rendering(data, resolution)
            })
          }
          _data.reverse()
          datafeed.fillData(_data, resolution, onHistoryCallback)
        })
    } catch (err) {
      console.log(err)
    }
  },
  fillCurrentLastDate: (data, to, resolution, callback) => {
    let step = 0
    let value = data
    let tmp = value[0] || null
    let currentTimeMap = 0
    let timemap = 0;
    /\d+/.test(resolution) && (step = resolution * 60 * 1000);
    /D/.test(resolution) && (step = 1 * 24 * 60 * 60 * 1000);

    if (resolution === 'D') {
      currentTimeMap = new Date(Utils.formatDate(new Date(), 'yyyy-MM-dd 00:00:000')).getTime()
      timemap = currentTimeMap
    } else {
      currentTimeMap = new Date().getTime()
      timemap = currentTimeMap - (currentTimeMap % step)
    }
    if (tmp && timemap !== tmp.time) {
      if (timemap > tmp.time) {
        value.unshift({
          close: tmp.close || 0,
          open: tmp.close || 0,
          high: tmp.close || 0,
          low: tmp.close || 0,
          time: timemap,
          volume: 0
        })
      }
    }
    callback && callback(value)
  },
  fillData: (_data, resolution, onHistoryCallback) => {
    // 填充中间缺少的数据，OHLC取上一个值，成交量取0
    let step = 0;
    /\d+/.test(resolution) && (step = resolution * 60 * 1000);
    /D/.test(resolution) && (step = 1 * 24 * 60 * 60 * 1000);
    /W/.test(resolution) && (step = 1 * 7 * 24 * 60 * 60 * 1000);

    if (_data.length && step) {
      let i = 0
      let qty = 0
      let tmp = {}
      while (_data[i + 1]) {
        qty = (_data[i + 1].time - _data[i].time) / step
        if (qty >= 2) {
          // console.log('qty', new Date(_data[i].time), new Date(_data[i + 1].time), qty)
          --qty
          // console.log('first', new Date(_data[i].time), i)
          for (let j = 0; j < qty; j++) {
            // tmp = Utils.copyObject(_data[i])
            tmp = {}
            tmp.close = _data[i].close
            tmp.open = tmp.close
            tmp.high = tmp.close
            tmp.low = tmp.close
            tmp.time = _data[i].time + step
            tmp.volume = 0
              ++i
            _data.splice(i, 0, tmp)
            // console.log('tmp', new Date(tmp.time), i)
          }
          ++i
        } else {
          ++i
        }
      }
    }

    onHistoryCallback(_data, { 'noData': (!_data || !_data.length) || false })
    _.isFunction(tradingView.options.afterSwitchPair) && tradingView.options.afterSwitchPair()
  },
  fillDataFeature: (_data, resolution, step) => {
    let value = _data
    if (value.length) {
      let i = value.length - 1
      let tmp = {}
      if (value[i].time <= value[i - 1].time + step) {
        if (global.TradingData.length > 0) {
          let tdata = global.TradingData[global.TradingData.length - 1]
          if (tdata.time !== value[i].time + step) {
            tmp.close = value[i].close
            tmp.open = value[i].open
            tmp.high = value[i].high
            tmp.low = value[i].low
            tmp.time = value[i].time + step
            tmp.volume = 0
          }
        } else {
          tmp.close = value[i].close
          tmp.open = value[i].open
          tmp.high = value[i].high
          tmp.low = value[i].low
          tmp.time = value[i].time + step
          tmp.volume = 0
        }
      }

      if (tmp) {
        value.push(tmp)
        global.TradingData.push(tmp)
        Utils.isFunction(global.params.KLinesDataCallback) && global.params.KLinesDataCallback(Utils.copyObject(tmp))
      }
    }
  },
  // K线实时数据绘制
  rendering: (data, resolution) => {
    let step = 0
    let delay = 0
    let currentTimeMap = 0
    let timemap = 0;
    /\d+/.test(resolution) && (step = resolution * 60 * 1000);
    /D/.test(resolution) && (step = 1 * 24 * 60 * 60 * 1000);

    if (resolution === 'D') {
      currentTimeMap = new Date(Utils.formatDate(new Date(), 'yyyy-MM-dd 00:00:000')).getTime()
    } else {
      currentTimeMap = new Date().getTime()
    }
    currentTimeMap = new Date().getTime()
    delay = step - (currentTimeMap % step)
    global.timeout && clearTimeout(global.timeout)
    global.timeout = null

    global.timeout = setTimeout(function() {
      if (delay !== step) {
        datafeed.fillDataFeature(data, resolution, step)
      }
      global.timer && clearInterval(global.timer)
      global.timer = null
      global.timer = window.setInterval(function() {
        datafeed.fillDataFeature(data, resolution, step)
      }, step)
    }, delay < 0 ? 0 : delay)
  },
  subscribeBars: (symbolInfo, resolution, onRealtimeCallback, subscriberUID, onResetCacheNeededCallback) => {
    // console.log('subscribeBars', symbolInfo, resolution)
    tradingViewHandle.onRealtimeCallback = onRealtimeCallback
  },
  unsubscribeBars: (subscriberUID) => {
    global.timeout && clearTimeout(global.timeout)
    global.timeout = null
    global.timer && clearInterval(global.timer)
    global.timer = null
    console.log('unsubscribeBars')
  },
  calculateHistoryDepth: (resolution, resolutionBack, intervalBack) => {
    // console.log('calculateHistoryDepth')
  },
  getMarks: (symbolInfo, startDate, endDate, onDataCallback, resolution) => {
    // console.log('getMarks')
  },
  getTimescaleMarks: (symbolInfo, startDate, endDate, onDataCallback, resolution) => {
    // console.log('getTimescaleMarks')
  },
  getServerTime: (callback) => {
    // console.log('getServerTime')
    // callback()
  }
}

tradingView = {
  data: [],
  upColor: '#3f7342',
  downColor: '#8b2626',
  tradingModuleBgColor: '#191f2b',
  run(options) {
    options.defaultResolution = options.defaultResolution || '1'
    this.options = options
    _.isFunction(this.options.beforeSwitchPair) && this.options.beforeSwitchPair()
    tradingView.pageIndex = 0
    this.widget = new options.TradingViewWidget({
      fullscreen: false, // 是否全屏
      timezone: 'Asia/Hong_Kong',
      width: '100%', // $('#tab_ChartContent').width(),
      height: '100%', // $('#tab_ChartContent').height(),
      custom_css_url: '/static/charting_library/static/tv-theme-dark.css',
      symbol: options.pair.Symbol, // 产品(交易对)
      interval: options.defaultResolution,
      container_id: 'swTradingView',
      // BEWARE: no trailing slash is expected in feed URL
      datafeed: datafeed,
      // new Datafeeds.UDFCompatibleDatafeed('http://localhost:8888'),
      library_path: '/static/charting_library/',
      locale: tradingView.fixLangKeyForTV(tradingView.options.language),
      // Regression Trend-related functionality is not implemented yet, so it's hidden for a while
      drawings_access: {
        type: 'black',
        tools: [
          { name: 'Regression Trend' }
        ]
      },
      disabled_features: [
        'header_symbol_search',
        'header_resolutions',
        'symbol_info',
        'header_compare',
        'use_localstorage_for_settings',
        'save_chart_properties_to_local_storage',
        'header_chart_type',
        'display_market_status',
        'symbol_search_hot_key',
        'compare_symbol',
        'border_around_the_chart',
        'remove_library_container_border',
        'symbol_info',
        'header_interval_dialog_button',
        'show_interval_dialog_on_key_press',
        'left_toolbar',
        'header_undo_redo',
        'header_screenshot',
        'volume_force_overlay'
        // 'timeframes_toolbar'
      ],
      enabled_features: [
        'dont_show_boolean_study_arguments', // 去掉false
        'hide_last_na_study_output' // 去掉 n/a
      ],
      overrides: {
        'paneProperties.background': this.tradingModuleBgColor,

        'paneProperties.vertGridProperties.color': '#2b323f', // 图表栅格线
        'paneProperties.vertGridProperties.style': 1,
        'paneProperties.horzGridProperties.color': '#2b323f',
        'paneProperties.horzGridProperties.style': 1,

        'paneProperties.crossHairProperties.color': '#989898', // 十字线
        'scalesProperties.backgroundColor': this.tradingModuleBgColor, // 左上角工具栏高亮后的背景色
        'scalesProperties.textColor': '#999', // 左上角文字颜色
        'scalesProperties.showLeftScale': false, // 决定纵坐标放在左还是右
        'scalesProperties.showRightScale': true,

        'mainSeriesProperties.candleStyle.upColor': this.upColor,
        'mainSeriesProperties.candleStyle.downColor': this.downColor,
        'mainSeriesProperties.candleStyle.drawWick': true, // 是否显示上下阴
        'mainSeriesProperties.candleStyle.drawBorder': true, // 是否显示边框
        // 'mainSeriesProperties.candleStyle.borderColor': '',
        'mainSeriesProperties.candleStyle.borderUpColor': this.upColor,
        'mainSeriesProperties.candleStyle.borderDownColor': this.downColor,
        'mainSeriesProperties.candleStyle.wickUpColor': this.upColor,
        'mainSeriesProperties.candleStyle.wickDownColor': this.downColor,
        'mainSeriesProperties.candleStyle.barColorsOnPrevClose': false,

        'mainSeriesProperties.hollowCandleStyle.upColor': this.upColor,
        'mainSeriesProperties.hollowCandleStyle.downColor': this.downColor,
        'mainSeriesProperties.hollowCandleStyle.drawWick': true,
        'mainSeriesProperties.hollowCandleStyle.drawBorder': true,
        // 'mainSeriesProperties.hollowCandleStyle.borderColor': '',
        'mainSeriesProperties.hollowCandleStyle.wickUpColor': this.upColor,
        'mainSeriesProperties.hollowCandleStyle.wickDownColor': this.downColor,
        'mainSeriesProperties.hollowCandleStyle.borderUpColor': this.upColor,
        'mainSeriesProperties.hollowCandleStyle.borderDownColor': this.downColor,
        // 'mainSeriesProperties.hollowCandleStyle.wickColor': '',

        // Heiken Ashi styles
        'mainSeriesProperties.haStyle.upColor': this.upColor,
        'mainSeriesProperties.haStyle.downColor': this.downColor,
        'mainSeriesProperties.haStyle.drawWick': true,
        'mainSeriesProperties.haStyle.drawBorder': false,
        // 'mainSeriesProperties.haStyle.borderColor': '',
        'mainSeriesProperties.haStyle.borderUpColor': this.upColor,
        'mainSeriesProperties.haStyle.borderDownColor': this.downColor,
        // 'mainSeriesProperties.haStyle.wickColor': '',
        'mainSeriesProperties.haStyle.wickUpColor': this.upColor,
        'mainSeriesProperties.haStyle.wickDownColor': this.downColor,
        'mainSeriesProperties.haStyle.barColorsOnPrevClose': false,

        // Bars styles
        'mainSeriesProperties.barStyle.upColor': this.upColor,
        'mainSeriesProperties.barStyle.downColor': this.downColor,
        'mainSeriesProperties.barStyle.barColorsOnPrevClose': false,
        'mainSeriesProperties.barStyle.dontDrawOpen': false,

        'paneProperties.legendProperties.showStudyArguments': false, // 成交量指标相关
        'paneProperties.legendProperties.showStudyTitles': true,
        'paneProperties.legendProperties.showStudyValues': true,
        // 'paneProperties.legendProperties.showSeriesTitle': false,
        // 'paneProperties.legendProperties.showSeriesOHLC': false,

        'scalesProperties.lineColor': '#666', // volume分隔线
        'mainSeriesProperties.style': 1, // k线类型的索引  1实心 9空心
        'volumePaneSize': 'medium' // 技术分析线模块大小
      },
      toolbar_bg: this.tradingModuleBgColor,
      time_frames: [{
          text: '2y',
          resolution: 'D',
          title: '2Y',
          description: ''
        },
        {
          text: '1y',
          resolution: 'D',
          title: '1Y',
          description: ''
        },
        {
          text: '6m',
          resolution: '60',
          title: '6MN',
          description: ''
        },
        {
          text: '3m',
          resolution: '60',
          title: '3MN',
          description: ''
        }
      ],
      debug: false
      // enabled_features: [],
      // charts_storage_url: 'http://saveload.tradingview.com',
      // charts_storage_api_version: '1.1',
      // client_id: 'tradingview.com',
      // user_id: 'public_user_id'
    })

    this.widget.onChartReady(() => {
      this.custom()

      tradingViewHandle.setLanguage = (langKey) => {
        tradingView.options.language = langKey
        this.pageIndex = 0
        // this.widget.setLanguage(tradingView.options.language) // widget.setLanguage会导致TV初始化

        // this.custom() 由于tradingViewHandle.setLanguage是在别处调用widget.createButton
        // 它会返回this._innerWindow().createButton，由于this指向问题，会导致_innerWindow()返回为空

        // 采用run重新运行代替widget.setLanguage
        this.run(tradingView.options)
      }
    })
    return tradingViewHandle
  },
  fixLangKeyForTV(langKey) {
    switch (langKey) {
      case 'zh-CN':
        langKey = 'zh'
        break
      case 'nl':
        langKey = 'nl_NL'
        break
      case 'zh-Hant':
        langKey = 'zh_TW'
        break
    }
    return langKey
  },
  createNode(tag, html) {
    let node = document.createElement(tag)
    node.innerHTML = html
    return node
  },
  createResolutionButton(resolution, title) {
    // 重要BUG：在IE11下初次加载正常，当切换交易对重新初始化tv时
    // 会报错无法读取null或者undefined的属性prototype
    // 原因可能是TV内置了1.7的jq版本与本项目的2.xjq版本冲突了
    // 重新用$再包装一次解决
    let TVNode = $(this.widget.createButton())
    TVNode.attr({
      title: title,
      'data-resolution': resolution
    }).on('click', () => {
      global.timeout && clearTimeout(global.timeout)
      global.timeout = null
      global.timer && clearInterval(global.timer)
      global.timer = null
      TVNode.addClass('active').closest('.space-single').siblings().find('.active').removeClass('active')
      this.widget.setSymbol('', resolution, (res) => {})
    }).append(this.createNode('span', title))

    this.resolutionBtnNodes.push(TVNode)

    if (this.options.defaultResolution.toString() === resolution.toString())
      TVNode.addClass('active')
  },
  custom() {
    this.resolutionBtnNodes = []
    this.createResolutionButton(1, 'M1')
    this.createResolutionButton(5, 'M5')
    this.createResolutionButton(15, 'M15')
    this.createResolutionButton(30, 'M30')
    this.createResolutionButton(60, 'H1')
    this.createResolutionButton('D', 'D1')
    this.createResolutionButton('W', 'W1')
    this.createResolutionButton('M', 'MN')
  }
}

export default tradingView
